/*
 * @Author: error: error: git config user.name & please set dead value or install git && error: git config user.email &
 * please set dead value or install git & please set dead value or install git
 * @Date: 2024-11-03 11:05:16
 * @LastEditors: yoola youlikesoilove@qq.com
 * user.email & please set dead value or install git & please set dead value or install git
 * @LastEditTime: 2024-12-08 23:44:06
 * @FilePath: \CrabSystemProject\src\requestFunc\requestPhoto.cc
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置:
 * https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#include <iostream>
#include <thread>
#include <chrono>
#include <cstring>  // for std::strerror
#include <errno.h>  // for errno
#include <fcntl.h>  // for open
#include <atomic>

#ifdef _WIN32
#include <windows.h>
const char* pipe_path = R"(\\.\pipe\capture_pipe)";
const char* response_pipe_path = R"(\\.\pipe\response_pipe)";
#else
#include <sys/stat.h>  // for mkfifo
#include <unistd.h>    // POSIX API函数，如 unlink、read 和 close
#include <fcntl.h>     // 如果有open、O_RDONLY 等使用
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/select.h>  //select
#include <errno.h>
#include <csignal>  // for signal handling
const char* pipe_path = "/tmp/capture_pipe";
#endif

std::atomic<bool> running(true);  // 用于控制线程运行状态

#ifdef _WIN32
BOOL WINAPI ConsoleHandler(DWORD signal) {
    if (signal == CTRL_C_EVENT || signal == CTRL_CLOSE_EVENT) {
        running = false;  // 设置为停止运行状态
        return TRUE;
    }
    return FALSE;
}
#else
void signal_handler(int signal) {
    running = false;  // 设置为停止运行状态
    exit(1);
}
#endif

#ifndef DISABLE_DIRECT_OUTPUT
#include <chrono>
#include <iomanip>
#include <sstream>
#define GET_LOCAL_TIME                                                                                      \
    []() {                                                                                                  \
        auto now = std::chrono::system_clock::now();                                                        \
        auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 1000;     \
        std::time_t t = std::chrono::system_clock::to_time_t(now);                                          \
        std::tm tm = *std::localtime(&t);                                                                   \
        std::ostringstream oss;                                                                             \
        oss << std::put_time(&tm, "%Y-%m-%d %H:%M:%S.") << std::setw(3) << std::setfill('0') << ms.count(); \
        return oss.str();                                                                                   \
    }()
#define FILE_LINE   " - " << __FILE__ << "[" << __LINE__ << "] -  "
#define OUTPUT_ERRR std::cerr << GET_LOCAL_TIME << FILE_LINE
#define OUPUT_INFO  std::cout << GET_LOCAL_TIME << FILE_LINE
#endif

int send_capture_signal() {
#ifdef _WIN32
    while (running) {
        HANDLE hPipe = CreateFileA(pipe_path, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);

        if (hPipe != INVALID_HANDLE_VALUE) {
            std::string message = "capture";  // 要发送的消息
            DWORD bytesWritten;

            // 向管道写入数据
            if (WriteFile(hPipe, message.c_str(), message.length(), &bytesWritten, NULL) == false) {
                OUTPUT_ERRR << "Failed to write to pipe: " << GetLastError() << std::endl;
                CloseHandle(hPipe);
                return 1;  // 退出程序
            }

            // 等待响应
            char buffer[256];
            DWORD bytesRead;

            if (ReadFile(hPipe, buffer, sizeof(buffer) - 1, &bytesRead, NULL) == false) {
                OUTPUT_ERRR << "Failed to read from pipe: " << GetLastError() << std::endl;
                CloseHandle(hPipe);
                return 1;  // 退出程序
            }
            buffer[bytesRead] = '\0';  // 确保字符串结束

            OUPUT_INFO << "Received from server: " << buffer << std::endl;
            CloseHandle(hPipe);
            return 0;  // 成功完成后退出循环
        } else {
            OUTPUT_ERRR << "Failed to connect to the named pipe: " << GetLastError() << ". Retrying..." << std::endl;
            std::this_thread::sleep_for(std::chrono::seconds(1));  // 等待1秒后重试
        }
        // 关闭管道句柄
        CloseHandle(hPipe);
    }
#else.
    int write_repeat_times = 0;
    while (running) {
        // 尝试以只写模式打开命名管道
        int w_fd = open(pipe_path, O_WRONLY | O_NONBLOCK);  // 非阻塞式
        if (write_repeat_times >= 10) {
            close(w_fd);  // 关闭写入管道
            return 1;
        } else if (w_fd == -1) {
            write_repeat_times++;
            OUTPUT_ERRR << "Failed to open named pipe for reading: " << std::strerror(errno) << std::endl;
            std::this_thread::sleep_for(std::chrono::milliseconds(100));  // 等待重试
            close(w_fd);                                                  // 关闭写入管道
            continue;                                                     // 继续循环
        }

        const char* message = "CAP_559";  // 要发送的消息
        if (write(w_fd, message, strlen(message)) == -1) {
            write_repeat_times++;
            OUTPUT_ERRR << "Failed to write to named pipe: " << std::strerror(errno) << std::endl;
            close(w_fd);  // 关闭写入管道
            continue;
        } else {
            OUPUT_INFO << "wirting ok!" << std::endl;
            close(w_fd);  // 关闭写入管道
        }

        int r_fd = open(pipe_path, O_RDONLY);  // 以只读模式打开响应管道

        // 设置超时时间
        struct timeval timeout;
        timeout.tv_sec = 10;  // 超时 10 秒
        timeout.tv_usec = 0;

        // 准备监控的文件描述符集合
        fd_set readfds;
        FD_ZERO(&readfds);
        FD_SET(r_fd, &readfds);

        // 使用 select 等待输入或超时
        int retval = select(r_fd + 1, &readfds, NULL, NULL, &timeout);
        if (retval == -1) {
            perror("select()");
        } else if (retval == 0) {
            OUPUT_INFO << "Timeout occurred! No data after " << timeout.tv_sec << " seconds." << std::endl;
            return 1;
        } else {
            // 读取数据
            char buffer[256];
            ssize_t bytesRead = read(r_fd, buffer, sizeof(buffer) - 1);  // 读取数据
            buffer[bytesRead] = '\0';                                    // 确保字符串结束
            OUPUT_INFO << "Received from server: " << buffer << std::endl;
            return 0;
        }
    }
#endif
}

int main() {
#ifdef _WIN32
    SetConsoleCtrlHandler(ConsoleHandler, TRUE);  // 捕获 Ctrl+C 和关闭事件
#else
    signal(SIGINT, signal_handler);  // 捕获 Ctrl+C 信号
#endif
    send_capture_signal();  // 发送拍照信号
    return 0;
}
